package com.siecom.module;

import android.util.Log;

import com.siecom.bean.APDU_RESP;
import com.siecom.bean.APDU_SEND;
import com.siecom.constconfig.ConstDefine;
import com.siecom.constconfig.ErrorDefine;
import com.siecom.nativelibs.rkGpioControlNative;
import com.siecom.tool.ByteTool;

import java.io.InputStream;
import java.io.OutputStream;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;

/**
 * Created by zhq on 2016/7/7.
 */
public class FinancialModule extends SerialPortModule {

    public final static String TAG = "FinancialModule";
    private static FinancialModule ourInstance = new FinancialModule();


    private OutputStream mOutputStream;
    private InputStream mInputStream;

    private int g_PrnStartFlag = 0;

    public static FinancialModule getInstance() {
        return ourInstance;
    }

    private String serialDev;
    private int baudRate = 115200;
    protected boolean isOpen = false;

    public int Icc_Command(byte slot, APDU_SEND ApduSend, APDU_RESP ApduResp) {

        flush();
        byte[] send = new byte[512];
        byte[] recv = new byte[512];
        short[] recvlen = new short[1];
        byte byModules = (byte) 0xc1;
        byte byFuntcion = (byte) 0x05;
        send[0] = slot;
        System.arraycopy(ApduSend.Command, 0, send, 1, 4);
        send[5] = (byte) (ApduSend.Lc / 256);
        send[6] = (byte) (ApduSend.Lc % 256);
        System.arraycopy(ApduSend.DataIn, 0, send, 7, ApduSend.Lc);
        send[(7 + ApduSend.Lc)] = (byte) (ApduSend.Le / 256);
        send[(8 + ApduSend.Lc)] = (byte) (ApduSend.Le % 256);
        Crc16SendPacket(send, (short)(ApduSend.Lc + 9),byModules,byFuntcion);

        if (Crc16RecvPacket(recv, recvlen, 2000) == 0) {
            if (recv[1] != byModules && (recv[2] - 1) != byFuntcion) {
                flush();
                return ErrorDefine.RECV_PACKET_ERROR;
            }
            if (((recv[6] & 0xff) | ((recv[5] << 8) & 0xff00)) == 0) {
                ApduResp.LenOut = (short) ((recv[3] & 0xFF) * 256
                        + (recv[4] & 0xFF) - 4);
                System.arraycopy(recv, 7, ApduResp.DataOut, 0,
                        ApduResp.LenOut);
                ApduResp.SWA = recv[(ApduResp.LenOut + 7)];
                ApduResp.SWB = recv[(ApduResp.LenOut + 8)];
                return 0 - (recv[6] & 0xff) | ((recv[5] << 8) & 0xff00);
            }
        }
        return -1;

    }

    public int setDateTime(byte[] dateTime) {
        flush();
        byte[] recv = new byte[1024];
        short[] recvlen = new short[1];
        byte byModules = (byte) 0xd1;
        byte byFuntcion = (byte) 0x01;
        Crc16SendPacket(dateTime, (short) dateTime.length, byModules, byFuntcion);
        if (Crc16RecvPacket(recv, recvlen, 2000) == 0) {
            if (recv[1] != byModules && (recv[2] - 1) != byFuntcion) {
                flush();
                return ErrorDefine.RECV_PACKET_ERROR;
            }
            return 0 - (recv[6] & 0xff) | ((recv[5] << 8) & 0xff00);
        }
        return -1;

    }

    /**
     * 读取圈存日志
     * @param slot
     * @return
     */
    public int EmvLib_GetLoadLog(byte slot, byte[] tlog, int[] length) {
        flush();
        byte[] send = new byte[1];
        send[0] = slot;
        byte[] recv = new byte[500];
        short[] recvlen = new short[1];
        byte byModules = (byte) 0xc5;
        byte byFuntcion = (byte) 0x34;
        Crc16SendPacket(send, (short) 1, byModules, byFuntcion);
        if (Crc16RecvPacket(recv, recvlen, 2000) == 0) {
            if (recv[1] != byModules && (recv[2] - 1) != byFuntcion) {
                flush();
                return ErrorDefine.RECV_PACKET_ERROR;
            }
            if (((recv[6] & 0xff) | ((recv[5] << 8) & 0xff00)) == 0) {
                length[0] = ((recv[4] & 0xff) | ((recv[3] << 8) & 0xff00)) - 2;
//                Log.e("len:",length[0]+"---");
                System.arraycopy(recv, 7, tlog, 0, length[0] - 2);
            }
            return 0 - (recv[6] & 0xff) | ((recv[5] << 8) & 0xff00);
        }
        return -1;

    }



    public int EmvLib_GetPan(int solt, byte[] cardno, int[] length) {
        flush();
        byte[] send = new byte[1];
        send[0] = (byte) solt;
        byte[] recv = new byte[1024];
        short[] recvlen = new short[1];
        byte byModules = (byte) 0xc4;
        byte byFuntcion = (byte) 0x01;
        Crc16SendPacket(send, (short) 1, byModules, byFuntcion);
        if (Crc16RecvPacket(recv, recvlen, 2000) == 0) {
            if (recv[1] != byModules && (recv[2] - 1) != byFuntcion) {
                flush();
                return ErrorDefine.RECV_PACKET_ERROR;
            }
            if (((recv[6] & 0xff) | ((recv[5] << 8) & 0xff00)) == 0) {

                length[0] = (recv[4] & 0xff) | ((recv[3] << 8) & 0xff00);
                System.arraycopy(recv, 7, cardno, 0, length[0] - 2);
            }
            return 0 - (recv[6] & 0xff) | ((recv[5] << 8) & 0xff00);
        }
        return -1;

    }

    public int EmvLib_SetSelectApp(int index) {
        flush();
        byte[] send = new byte[1];
        send[0] = (byte) index;
        byte[] recv = new byte[1024];
        short[] recvlen = new short[1];
        byte byModules = (byte) 0xc5;
        byte byFuntcion = (byte) 0x2d;
        Crc16SendPacket(send, (short) 1, byModules, byFuntcion);
        if (Crc16RecvPacket(recv, recvlen, 2000) == 0) {
            if (recv[1] != byModules && (recv[2] - 1) != byFuntcion) {
                flush();
                return ErrorDefine.RECV_PACKET_ERROR;
            }
            return 0 - (recv[4] & 0xff) | ((recv[3] << 8) & 0xff00);
        }
        return -1;

    }


    public int EmvLib_CoreGetAmt(int AuthAmount, int BackAmt) {
        flush();
        byte[] send = new byte[16];
        byte[] recv = new byte[1024];

        byte[] tmp = String.valueOf(AuthAmount).getBytes();
        System.arraycopy(tmp, 0, send, 0, tmp.length);
        tmp = String.valueOf(BackAmt).getBytes();
        System.arraycopy(tmp, 0, send, 8, tmp.length);

        short[] recvlen = new short[1];
        byte byModules = (byte) 0xc5;
        byte byFuntcion = (byte) 0x2b;
        Crc16SendPacket(send, (short) 16, byModules, byFuntcion);
        if (Crc16RecvPacket(recv, recvlen, 2000) == 0) {
            if (recv[1] != byModules && (recv[2] - 1) != byFuntcion) {
                flush();
                return ErrorDefine.RECV_PACKET_ERROR;
            }

            return 0 - (recv[6] & 0xff) | ((recv[5] << 8) & 0xff00);
        }
        return -1;


    }

    public int EmvLib_ClearTransLog() {
        flush();
        byte[] send = new byte[1];
        byte[] recv = new byte[1024];
        short[] recvlen = new short[1];
        byte byModules = (byte) 0xc5;
        byte byFuntcion = (byte) 0x25;
        Crc16SendPacket(send, (short) 0, byModules, byFuntcion);
        if (Crc16RecvPacket(recv, recvlen, 2000) == 0) {
            if (recv[1] != byModules && (recv[2] - 1) != byFuntcion) {
                flush();
                return ErrorDefine.RECV_PACKET_ERROR;
            }

            return 0 - (recv[6] & 0xff) | ((recv[5] << 8) & 0xff00);
        }
        return -1;
    }


    public int EmvLib_AddCapk(byte[] capk) {
        flush();
        byte[] recv = new byte[1024];
        short[] recvlen = new short[1];
        byte byModules = (byte) 0xc5;
        byte byFuntcion = (byte) 0x21;
        Crc16SendPacket(capk, (short) 284, byModules, byFuntcion);
        if (Crc16RecvPacket(recv, recvlen, 2000) == 0) {
            if (recv[1] != byModules && (recv[2] - 1) != byFuntcion) {
                flush();
                return ErrorDefine.RECV_PACKET_ERROR;
            }

            return 0 - (recv[6] & 0xff) | ((recv[5] << 8) & 0xff00);
        }
        return -1;
    }


    public int EmvLib_SetParam(byte[] param) {
        flush();
        byte[] recv = new byte[1024];
        short[] recvlen = new short[1];
        byte byModules = (byte) 0xc5;
        byte byFuntcion = (byte) 0x21;
        Crc16SendPacket(param, (short) 142, byModules, byFuntcion);
        if (Crc16RecvPacket(recv, recvlen, 2000) == 0) {
            if (recv[1] != byModules && (recv[2] - 1) != byFuntcion) {
                flush();
                return ErrorDefine.RECV_PACKET_ERROR;
            }

            return 0 - (recv[6] & 0xff) | ((recv[5] << 8) & 0xff00);
        }
        return -1;

    }


    public int EmvLib_AddApp(byte[] applist) {
        flush();
        byte[] recv = new byte[1024];
        short[] recvlen = new short[1];
        byte byModules = (byte) 0xc5;
        byte byFuntcion = (byte) 0x1d;
        Crc16SendPacket(applist, (short) 251, byModules, byFuntcion);
        if (Crc16RecvPacket(recv, recvlen, 2000) == 0) {
            if (recv[1] != byModules && (recv[2] - 1) != byFuntcion) {
                flush();
                return ErrorDefine.RECV_PACKET_ERROR;
            }

            return 0 - (recv[6] & 0xff) | ((recv[5] << 8) & 0xff00);
        }
        return -1;
    }


    public int EmvLib_GetLog(byte slot, byte[] tlog, int[] length) {
        flush();
        byte[] send = new byte[1];
        send[0] = slot;
        byte[] recv = new byte[500];
        short[] recvlen = new short[1];
        byte byModules = (byte) 0xc5;
        byte byFuntcion = (byte) 0x32;
        Crc16SendPacket(send, (short) 1, byModules, byFuntcion);
        if (Crc16RecvPacket(recv, recvlen, 2000) == 0) {
            if (recv[1] != byModules && (recv[2] - 1) != byFuntcion) {
                flush();
                return ErrorDefine.RECV_PACKET_ERROR;
            }
            if (((recv[6] & 0xff) | ((recv[5] << 8) & 0xff00)) == 0) {
                length[0] = ((recv[4] & 0xff) | ((recv[3] << 8) & 0xff00)) - 2;
//                Log.e("len:",length[0]+"---");
                System.arraycopy(recv, 7, tlog, 0, length[0] - 2);
            }
            return 0 - (recv[6] & 0xff) | ((recv[5] << 8) & 0xff00);
        }
        return -1;

    }


    public int EmvLib_GetCapk(int Index, byte[] capk, int[] len) {
        flush();
        byte[] send = new byte[1];
        send[0] = (byte) Index;
        byte[] recv = new byte[1024];
        short[] recvlen = new short[1];
        byte byModules = (byte) 0xc5;
        byte byFuntcion = (byte) 0x1b;
        Crc16SendPacket(send, (short) 1, byModules, byFuntcion);
        if (Crc16RecvPacket(recv, recvlen, 2000) == 0) {
            if (recv[1] != byModules && (recv[2] - 1) != byFuntcion) {
                flush();
                return ErrorDefine.RECV_PACKET_ERROR;
            }
            if (((recv[6] & 0xff) | ((recv[5] << 8) & 0xff00)) == 0) {
                len[0] = (recv[4] & 0xff) | ((recv[3] << 8) & 0xff00);
                System.arraycopy(recv, 7, capk, 0, len[0] - 2);
            }
            return 0 - (recv[6] & 0xff) | ((recv[5] << 8) & 0xff00);
        }
        return -1;
    }


    public int EmvLib_GetParam(byte[] params, int[] len) {
        flush();
        byte[] send = new byte[2];
        send[0] = 0x00;
        send[1] = 0x00;
        byte[] recv = new byte[150];
        short[] recvlen = new short[1];
        byte byModules = (byte) 0xc5;
        byte byFuntcion = (byte) 0x19;
        Crc16SendPacket(send, (short) 2, byModules, byFuntcion);
        if (Crc16RecvPacket(recv, recvlen, 2000) == 0) {
            if (recv[1] != byModules && (recv[2] - 1) != byFuntcion) {
                flush();
                return ErrorDefine.RECV_PACKET_ERROR;
            }
            if (((recv[6] & 0xff) | ((recv[5] << 8) & 0xff00)) == 0) {
                len[0] = (recv[4] & 0xff) | ((recv[3] << 8) & 0xff00);
                System.arraycopy(recv, 5, params, 0, len[0] - 2);
            }
            return 0 - (recv[6] & 0xff) | ((recv[5] << 8) & 0xff00);
        }
        return -1;
    }


    public int EmvLib_GetApp(int Index, byte[] App, int[] len) {
        flush();
        byte[] send = new byte[1];
        send[0] = (byte) Index;
        byte[] recv = new byte[1024];
        short[] recvlen = new short[1];
        byte byModules = (byte) 0xc5;
        byte byFuntcion = (byte) 0x17;
        Crc16SendPacket(send, (short) 1, byModules, byFuntcion);
        if (Crc16RecvPacket(recv, recvlen, 2000) == 0) {
            if (recv[1] != byModules && (recv[2] - 1) != byFuntcion) {
                flush();
                return ErrorDefine.RECV_PACKET_ERROR;
            }
            if (((recv[6] & 0xff) | ((recv[5] << 8) & 0xff00)) == 0) {
                len[0] = (recv[4] & 0xff) | ((recv[3] << 8) & 0xff00);
                System.arraycopy(recv, 7, App, 0, len[0] - 2);
            }
            return 0 - (recv[6] & 0xff) | ((recv[5] << 8) & 0xff00);
        }
        return -1;
    }


    public int EmvLib_GetTags(String[] tags, byte[] dataOut, int[] len) {
        flush();
        byte[] send = new byte[512];
        byte[] recv = new byte[1024];
        short[] recvlen = new short[1];
        int length = tags.length;
        String tmp = "";
        List lbyte = new ArrayList();
        for (int i = 0; i < length; i++) {
            tmp = tags[i];
            byte[] b = ByteTool.hexStr2Bytes(tmp);
            for (byte tmpb : b) {
                lbyte.add(tmpb);
            }
        }
        byte[] tb = new byte[lbyte.size()];
        for (int i = 0; i < tb.length; i++) {
            tb[i] = (Byte) lbyte.get(i);
        }
        int tagslen = lbyte.size();
        System.arraycopy(tb, 0, send, 0, tagslen);
        byte byModules = (byte) 0xc5;
        byte byFuntcion = (byte) 0x15;
        Crc16SendPacket(send, (short) tagslen, byModules, byFuntcion);
        if (Crc16RecvPacket(recv, recvlen, 2000) == 0) {
            if (recv[1] != byModules && (recv[2] - 1) != byFuntcion) {
                flush();
                return ErrorDefine.RECV_PACKET_ERROR;
            }
            if (((recv[6] & 0xff) | ((recv[5] << 8) & 0xff00)) == 0) {
                byte[] len1 = new byte[2];
                len1[0] = recv[3];
                len1[1] = recv[4];
                len[0] = ByteTool.byteArray2int(len1) - 2;
                System.arraycopy(recv, 7, dataOut, 0, len[0]);
            }
            return 0 - (recv[6] & 0xff) | ((recv[5] << 8) & 0xff00);
        }
        return -1;

    }

    public int EmvLib_GetScriptResult(byte[] Result, int[] RetLen) {
        flush();
        byte[] send = new byte[1];
        byte[] recv = new byte[1024];
        short[] recvlen = new short[1];
        byte byModules = (byte) 0xc5;
        byte byFuntcion = (byte) 0x13;
        Crc16SendPacket(send, (short) 0, byModules, byFuntcion);
        if (Crc16RecvPacket(recv, recvlen, 2000) == 0) {
            if (recv[1] != byModules && (recv[2] - 1) != byFuntcion) {
                flush();
                return ErrorDefine.RECV_PACKET_ERROR;
            }
            if (((recv[6] & 0xff) | ((recv[5] << 8) & 0xff00)) == 0) {
                RetLen[0] = ((recv[7] & 0xFF) * 256 + (recv[8] & 0xFF));
                System.arraycopy(recv, 9, Result, 0, RetLen[0]);
            }
            return 0 - (recv[6] & 0xff) | ((recv[5] << 8) & 0xff00);
        }
        return -1;
    }

    public int EmvLib_GetStatus() {
        flush();
        byte[] send = new byte[1];
        byte[] recv = new byte[1024];
        short[] recvlen = new short[1];
        byte byModules = (byte) 0xc5;
        byte byFuntcion = (byte) 0x11;
        Crc16SendPacket(send, (short) 0, byModules, byFuntcion);
        if (Crc16RecvPacket(recv, recvlen, 2000) == 0) {
            if (recv[1] != byModules && (recv[2] - 1) != byFuntcion) {
                flush();
                return ErrorDefine.RECV_PACKET_ERROR;
            }
            return (int) recv[7] & 0xFF;
        }
        return -1;

    }

    public int EmvLib_GetVer(byte[] version) {
        flush();
        byte[] send = new byte[1];
        byte[] recv = new byte[1024];
        short[] recvlen = new short[1];
        byte byModules = (byte) 0xc5;
        byte byFuntcion = (byte) 0x0d;
        Crc16SendPacket(send, (short) 0, byModules, byFuntcion);
        if (Crc16RecvPacket(recv, recvlen, 2000) == 0) {
            if (recv[1] != byModules && (recv[2] - 1) != byFuntcion) {
                flush();
                return ErrorDefine.RECV_PACKET_ERROR;
            }
            version[0] = recv[7];
            version[1] = recv[8];
            return 0;
        }
        return -1;
    }


    public int EmvLib_CreatAppList(byte Slot, byte ReadLogFlag,
                                   byte[] AidLists, int[] Num) {
        flush();
        byte[] send = new byte[2];
        byte[] recv = new byte[300];
        short[] recvlen = new short[1];
        send[0] = Slot;
        send[1] = ReadLogFlag;
        byte byModules = (byte) 0xc5;
        byte byFuntcion = (byte) 0x30;
        Crc16SendPacket(send, (short) 2, byModules, byFuntcion);
        if (Crc16RecvPacket(recv, recvlen, 2000) == 0) {
            if (recv[1] != byModules && (recv[2] - 1) != byFuntcion) {
                flush();
                return ErrorDefine.RECV_PACKET_ERROR;
            }


            Num[0] = (int) recv[7] & 0xFF;
            return 0 - (recv[6] & 0xff) | ((recv[5] << 8) & 0xff00);
        }
        return -1;

    }


    public int EmvLib_ProcCLTransComplete(byte Result, byte[] RspCode,
                                          byte[] AuthCode, int AuthCodeLen) {
        flush();
        byte[] send = new byte[5 + AuthCodeLen];
        byte[] recv = new byte[1024];
        short[] recvlen = new short[1];

        send[0] = Result;
        send[1] = RspCode[0];
        send[2] = RspCode[1];

        send[3] = (byte) (AuthCodeLen / 256);
        send[4] = (byte) (AuthCodeLen % 256);
        byte byModules = (byte) 0xc5;
        byte byFuntcion = (byte) 0x0b;
        System.arraycopy(AuthCode, 0, send, 5, AuthCodeLen);
        Crc16SendPacket(send, (short) 5, byModules, byFuntcion);
        if (Crc16RecvPacket(recv, recvlen, 2000) == 0) {
            if (recv[1] != byModules && (recv[2] - 1) != byFuntcion) {
                flush();
                return ErrorDefine.RECV_PACKET_ERROR;
            }
            return 0 - (recv[6] & 0xff) | ((recv[5] << 8) & 0xff00);
        }
        return -1;

    }

    public int EmvLib_ProcCLTransBeforeOnline(byte slot, int TransNo,
                                              byte[] bIfGoOnline, byte[] bIfNeedPin) {
        flush();
        byte[] send = new byte[5];
        send[0] = slot;
        short[] recvlen = new short[1];
        byte[] recv = new byte[1024];
        byte byModules = (byte) 0xc5;
        byte byFuntcion = (byte) 0x09;
        byte[] transNo = ByteTool.intTo4bytes(TransNo);
        Log.e("transNo:", ByteTool.byte2hex(transNo));
        System.arraycopy(transNo, 0, send, 1, 4);
        Crc16SendPacket(send, (short) 5, byModules, byFuntcion);
        if (Crc16RecvPacket(recv, recvlen, 2000) == 0) {
            if (recv[1] != byModules && (recv[2] - 1) != byFuntcion) {
                flush();
                return ErrorDefine.RECV_PACKET_ERROR;
            }
            return 0 - (recv[6] & 0xff) | ((recv[5] << 8) & 0xff00);
        }
        return -1;

    }

    public int EmvLib_qPBOCPreProcess() {
        flush();
        byte[] send = new byte[1];
        byte[] recv = new byte[1024];
        short[] recvlen = new short[1];
        byte byModules = (byte) 0xc5;
        byte byFuntcion = (byte) 0x07;
        Crc16SendPacket(send, (short) 0, byModules, byFuntcion);
        if (Crc16RecvPacket(recv, recvlen, 2000) == 0) {
            if (recv[1] != byModules && (recv[2] - 1) != byFuntcion) {
                flush();
                return ErrorDefine.RECV_PACKET_ERROR;
            }
            return 0 - (recv[6] & 0xff) | ((recv[5] << 8) & 0xff00);
        }
        return -1;


    }


    public int EmvLib_ProcTransComplete(byte ucResult, byte[] RspCode,
                                        byte[] AuthCode, int AuthCodeLen, byte[] IAuthData,
                                        int IAuthDataLen, byte[] script, int ScriptLen) {
        flush();
        byte[] send = new byte[300];
        byte[] recv = new byte[1024];
        short[] recvlen = new short[1];
        byte byModules = (byte) 0xc5;
        byte byFuntcion = (byte) 0x05;

        send[0] = ucResult;
        send[1] = RspCode[0];
        send[2] = RspCode[1];
        send[3] = (byte) (AuthCodeLen / 256);
        send[4] = (byte) (AuthCodeLen % 256);
        send[5] = (byte) (IAuthDataLen / 256);
        send[6] = (byte) (IAuthDataLen % 256);

        send[7] = (byte) (ScriptLen / 256);
        send[8] = (byte) (ScriptLen % 256);

        System.arraycopy(AuthCode, 0, send, 9, AuthCodeLen);
        System.arraycopy(IAuthData, 0, send, 9 + AuthCodeLen,
                IAuthDataLen);
        System.arraycopy(script, 0, send, 9 + AuthCodeLen
                + IAuthDataLen, ScriptLen);

        Crc16SendPacket(send, (short) (9 + AuthCodeLen
                + IAuthDataLen + ScriptLen), byModules, byFuntcion);
        if (Crc16RecvPacket(recv, recvlen, 2000) == 0) {
            if (recv[1] != byModules && (recv[2] - 1) != byFuntcion) {
                flush();
                return ErrorDefine.RECV_PACKET_ERROR;
            }
            return 0 - (recv[6] & 0xff) | ((recv[5] << 8) & 0xff00);
        }
        return -1;

    }

    public int EmvLib_Init() {
        flush();
        byte[] send = new byte[1];
        byte[] recv = new byte[1024];
        short[] recvlen = new short[1];
        byte byModules = (byte) 0xc5;
        byte byFuntcion = (byte) 0x01;
        Crc16SendPacket(send, (short) 0, byModules, byFuntcion);
        if (Crc16RecvPacket(recv, recvlen, 2000) == 0) {
            if (recv[1] != byModules && (recv[2] - 1) != byFuntcion) {
                flush();
                return ErrorDefine.RECV_PACKET_ERROR;
            }
            return 0 - (recv[6] & 0xff) | ((recv[5] << 8) & 0xff00);
        }
        return -1;
    }

    public int EmvLib_ProcTransBeforeOnline(byte solt, int TransNo, byte[] ifGoOnline, byte[] ifNeedPin) {
        flush();
        byte[] send = new byte[5];
        send[0] = solt;
        short[] recvlen = new short[1];
        byte[] recv = new byte[1024];
        byte byModules = (byte) 0xc5;
        byte byFuntcion = (byte) 0x03;
        byte[] transNo = ByteTool.intTo4bytes(TransNo);
        Log.e("transNo:", ByteTool.byte2hex(transNo));
        System.arraycopy(transNo, 0, send, 1, 4);
        Crc16SendPacket(send, (short) 5, byModules, byFuntcion);
        if (Crc16RecvPacket(recv, recvlen, 10000) == 0) {
            if (recv[1] != byModules && (recv[2] - 1) != byFuntcion) {
                flush();
                return ErrorDefine.RECV_PACKET_ERROR;
            }
            if (((recv[6] & 0xff) | ((recv[5] << 8) & 0xff00)) == 0) {
                ifGoOnline[0] = recv[7];
                ifNeedPin[0] = recv[8];
                return 0;
            } else {

                return 0 - (recv[6] & 0xff) | ((recv[5] << 8) & 0xff00);
            }
        }
        return -1;

    }

    private FinancialModule() {

        super();

    }

    public boolean init(){
        this.serialDev = ConstDefine.getFinancialPort();
        if(this.serialDev==null){
            isOpen = false;
            return false;
        }
        if (initSerialPort(this.serialDev, this.baudRate)) {
            Log.e(TAG, "open");
            isOpen = true;
            mOutputStream = serialPort.getOutputStream();
            mInputStream = serialPort.getInputStream();
            return  true;
        }
        return  false;
    }

    public int readVersion(byte[] bootVer, byte[] appVer) {
        flush();
        byte[] send = new byte[1];
        byte[] recv = new byte[1024];
        short[] recvlen = new short[1];
        byte byModules = (byte) 0xd1;
        byte byFuntcion = (byte) 0x05;
        Crc16SendPacket(send, (short) 0, byModules, byFuntcion);
        if (Crc16RecvPacket(recv, recvlen, 2000) == 0) {
            if (recv[1] != byModules && (recv[2] - 1) != byFuntcion) {
                flush();
                return ErrorDefine.RECV_PACKET_ERROR;
            }
            System.arraycopy(recv, 7, bootVer, 0, 3);
            System.arraycopy(recv, 10, appVer, 0, 3);
            return 0;
        }
        return -1;
    }


    public int libMcrOpen() {
        flush();
        byte[] send = new byte[2];
        byte[] recv = new byte[1024];
        short[] recvlen = new short[1];
        byte byModules = (byte) 0xc2;
        byte byFuntcion = (byte) 0x01;
        int result = -1;
        Crc16SendPacket(send, (short) 0, byModules, byFuntcion);
        if (Crc16RecvPacket(recv, recvlen, 1000) == 0) {
            if (recv[1] != byModules && (recv[2] - 1) != byFuntcion) {
                flush();
                return ErrorDefine.RECV_PACKET_ERROR;
            }
            result = 0 - (recv[6] & 0xff) | ((recv[5] << 8) & 0xff00);
        } else result = 1;
        return result;
    }

    public int libMcrClose() {
        flush();
        byte[] send = new byte[1];
        byte[] recv = new byte[1024];
        short[] recvlen = new short[1];
        byte byModules = (byte) 0xc2;
        byte byFuntcion = (byte) 0x03;
        int result = 0;
        Crc16SendPacket(send, (short) 0, byModules, byFuntcion);
        if (Crc16RecvPacket(recv, recvlen, 1000) == 0) {
            if (recv[1] != byModules && (recv[2] - 1) != byFuntcion) {
                flush();
                return ErrorDefine.RECV_PACKET_ERROR;
            }
            result = 0 - (recv[6] & 0xff) | ((recv[5] << 8) & 0xff00);
        } else result = 1;
        return result;
    }

    public int libMcrRead(byte[] track1, byte[] track2, byte[] track3) {
        byte[] send = new byte[200];
        byte[] recv = new byte[1024];
        short[] recvlen = new short[1];
        byte byModules = (byte) 0xc2;
        byte byFuntcion = (byte) 0x07;
        int result = 0;
        int SendLen;
        send[0] = 0;
        send[1] = 0;
        Crc16SendPacket(send, (short) 2, byModules, byFuntcion);
        if (Crc16RecvPacket(recv, recvlen, 3000) == 0) {

            if (recv[1] != byModules && (recv[2] - 1) != byFuntcion) {
                flush();
                return ErrorDefine.RECV_PACKET_ERROR;
            }

            result = 0 - (recv[6] & 0xff) | ((recv[5] << 8) & 0xff00);
            //track1
            if (recv[7] != 0) {
                System.arraycopy(recv, 10, track1, 0, recv[7]);

            }
            if (recv[8] != 0) {
                System.arraycopy(recv, 10 + recv[7], track2, 0, recv[8]);

            }
            if (recv[9] != 0) {
                System.arraycopy(recv, 10 + recv[7] + recv[8], track3, 0, recv[9]);

            }
        } else result = 0;

        return result;
    }

    public int libMcrCheck() {
        flush();
        byte[] send = new byte[1];
        byte[] recv = new byte[1024];
        short[] recvlen = new short[1];
        byte byModules = (byte) 0xc2;
        byte byFuntcion = (byte) 0x05;
        int result = 0;
        Crc16SendPacket(send, (short) 0, byModules, byFuntcion);
        if (Crc16RecvPacket(recv, recvlen, 1000) == 0) {
            if (recv[1] != byModules && (recv[2] - 1) != byFuntcion) {
                flush();
                return ErrorDefine.RECV_PACKET_ERROR;
            }
            result = ((int) recv[6] & 0xff) | (((int) recv[5] << 8) & 0xff00);
        } else result = 1;

        return result;
    }

    public int libIccOpen(byte slot, byte mode, byte[] attr) {
        flush();
        byte[] send = new byte[2];
        byte[] recv = new byte[1024];
        short[] recvlen = new short[1];
        byte byModules = (byte) 0xc1;
        byte byFuntcion = (byte) 0x01;
        int result = 0;
        send[0] = slot;
        send[1] = mode;
        Crc16SendPacket(send, (short) 2, byModules, byFuntcion);
        if (Crc16RecvPacket(recv, recvlen, 1000) == 0) {
            if (recv[1] != byModules && (recv[2] - 1) != byFuntcion) {
                flush();
                return ErrorDefine.RECV_PACKET_ERROR;
            }
            result = 0 - (recv[6] & 0xff) | ((recv[5] << 8) & 0xff00);
            if (result == 0) {
                //Log.i("RecvPacket", "" + ByteUtil.bytearrayToHexString(recv, recvlen[0]));
                try {
                    System.arraycopy(recv, 7, attr, 0, recv[7] + 1);
                } catch (ArrayIndexOutOfBoundsException e) {
                    e.printStackTrace();
                    return -1;
                }

            }
        } else result = 1;
        return result;
    }

    public int libIccCommand(byte slot, APDU_SEND apduS, APDU_RESP apduR) {
        flush();
        byte[] send = new byte[200];
        byte[] recv = new byte[1024];
        short[] recvlen = new short[1];
        byte byModules = (byte) 0xc1;
        byte byFuntcion = (byte) 0x05;
        int result = 1;
        int SendLen;
        send[0] = slot;
        byte[] apduSend = apduS.toBytesArray();
        byte[] apduResp = new byte[200];
        Log.i("RecvPacket", "" + ByteTool.bytearrayToHexString(apduSend, recvlen[0]));
        SendLen = (apduSend[5] & 0xff) | ((apduSend[4] << 8) & 0xff00);
        SendLen = SendLen + 9;
        //Log.i("apdusend", "" + ByteUtil.bytearrayToHexString(apduSend, SendLen));

        System.arraycopy(apduSend, 0, send, 1, SendLen - 1);

        Crc16SendPacket(send, (short) SendLen, byModules, byFuntcion);
        if (Crc16RecvPacket(recv, recvlen, 3000) == 0) {

            if (recv[1] != byModules && (recv[2] - 1) != byFuntcion) {
                flush();
                return ErrorDefine.RECV_PACKET_ERROR;
            }
            result = 0 - (recv[6] & 0xff) | ((recv[5] << 8) & 0xff00);
            if (result == 0) {
                apduResp[0] = (byte) (((recvlen[0] - 11) >> 8) & 0xff);
                apduResp[1] = (byte) ((recvlen[0] - 11) & 0xff);
                System.arraycopy(recv, 7, apduResp, 2, recvlen[0] - 9);
                APDU_RESP.parseFromByteArray(apduResp, apduR);
            }

        } else result = 1;

        return result;
    }

    public int libIccClose(byte slot) {
        flush();
        byte[] send = new byte[1];
        byte[] recv = new byte[1024];
        short[] recvlen = new short[1];
        byte byModules = (byte) 0xc1;
        byte byFuntcion = (byte) 0x03;
        int result = 0;

        send[0] = slot;

        Crc16SendPacket(send, (short) 1, byModules, byFuntcion);
        if (Crc16RecvPacket(recv, recvlen, 1000) == 0) {
            if (recv[1] != byModules && (recv[2] - 1) != byFuntcion) {
                flush();
                return ErrorDefine.RECV_PACKET_ERROR;
            }
            result = 0 - (recv[6] & 0xff) | ((recv[5] << 8) & 0xff00);
        } else result = 1;
        return result;
    }

    /**
     * 检测卡片
     *
     * @param slot
     * @return
     */
    public int libIccCheck(byte slot) {
        flush();
        byte[] send = new byte[1];
        byte[] recv = new byte[1024];
        short[] recvlen = new short[1];
        byte byModules = (byte) 0xc1;
        byte byFuntcion = (byte) 0x07;
        int result = 0;
        send[0] = slot;
        Crc16SendPacket(send, (short) 1, byModules, byFuntcion);
        if (Crc16RecvPacket(recv, recvlen, 1000) == 0) {
            if (recv[1] != byModules && (recv[2] - 1) != byFuntcion) {
                flush();
                return ErrorDefine.RECV_PACKET_ERROR;
            }
            result = ((int) recv[6] & 0xff) | (((int) recv[5] << 8) & 0xff00);
        } else result = 1;
        Log.e("libIccCheck",result+"==");
        return result;
    }

    public int libPiccCheck(byte mode, byte[] cardtype, byte[] snbuf) {
        flush();
        byte[] send = new byte[1];
        byte[] recv = new byte[1024];
        short[] recvlen = new short[1];
        byte byModules = (byte) 0xc3;
        byte byFuntcion = (byte) 0x05;
        int result = 0;
        send[0] = mode;
        Crc16SendPacket(send, (short) 1, byModules, byFuntcion);
        if (Crc16RecvPacket(recv, recvlen, 1000) == 0) {
            if (recv[1] != byModules && (recv[2] - 1) != byFuntcion) {
                flush();
                return ErrorDefine.RECV_PACKET_ERROR;
            }

            result = ((int) recv[6] & 0xff) | (((int) recv[5] << 8) & 0xff00);
            if (result == 0) {
                System.arraycopy(recv, 7, cardtype, 0, 2);
                System.arraycopy(recv, 9, snbuf, 0, recv[9] + 1);
            }
        } else result = 1;

        return result;
    }

    public int libPiccOpen() {
        flush();
        byte[] send = new byte[2];
        byte[] recv = new byte[1024];
        short[] recvlen = new short[1];
        byte byModules = (byte) 0xc3;
        byte byFuntcion = (byte) 0x01;
        int result = 0;

        Crc16SendPacket(send, (short) 0, byModules, byFuntcion);
        if (Crc16RecvPacket(recv, recvlen, 1000) == 0) {
            if (recv[1] != byModules && (recv[2] - 1) != byFuntcion) {
                flush();
                return ErrorDefine.RECV_PACKET_ERROR;
            }
            result = 0 - (recv[6] & 0xff) | ((recv[5] << 8) & 0xff00);
        } else result = 1;
        return result;
    }

    public int libPiccCommand(byte[] apduSend, byte[] apduResp) {
        flush();
        byte[] send = new byte[200];
        byte[] recv = new byte[1024];
        short[] recvlen = new short[1];
        byte byModules = (byte) 0xc3;
        byte byFuntcion = (byte) 0x07;
        int result = 1;
        int SendLen;

        Log.i("RecvPacket", "" + ByteTool.bytearrayToHexString(apduSend, recvlen[0]));
        SendLen = (apduSend[5] & 0xff) | ((apduSend[4] << 8) & 0xff00);
        SendLen = SendLen + 9;
        //Log.i("apdusend", "" + ByteUtil.bytearrayToHexString(apduSend, SendLen));

        System.arraycopy(apduSend, 0, send, 0, SendLen - 1);

        Crc16SendPacket(send, (short) SendLen, byModules, byFuntcion);
        if (Crc16RecvPacket(recv, recvlen, 3000) == 0) {
            if (recv[1] != byModules && (recv[2] - 1) != byFuntcion) {
                flush();
                return ErrorDefine.RECV_PACKET_ERROR;
            }
            result = 0 - (recv[6] & 0xff) | ((recv[5] << 8) & 0xff00);
            if (result == 0) {
                apduResp[0] = (byte) (((recvlen[0] - 11) >> 8) & 0xff);
                apduResp[1] = (byte) ((recvlen[0] - 11) & 0xff);
                System.arraycopy(recv, 7, apduResp, 2, recvlen[0] - 9);
            }

        } else result = 1;

        return result;
    }

    public int libPiccClose() {
        flush();
        byte[] send = new byte[1];
        byte[] recv = new byte[1024];
        short[] recvlen = new short[1];
        byte byModules = (byte) 0xc3;
        byte byFuntcion = (byte) 0x03;
        int result = 0;
        Crc16SendPacket(send, (short) 0, byModules, byFuntcion);
        if (Crc16RecvPacket(recv, recvlen, 1000) == 0) {
            if (recv[1] != byModules && (recv[2] - 1) != byFuntcion) {
                flush();
                return ErrorDefine.RECV_PACKET_ERROR;
            }
            result = 0 - (recv[6] & 0xff) | ((recv[5] << 8) & 0xff00);
        } else result = 1;
        return result;
    }

    public int Crc16RecvPacket(byte[] pbyRecvData, short[] pwPacketetLen,
                               int dwTimeoutMs) {

        byte[] abyCrc16 = new byte[2];
        int wDataLen = 0;
        int byRet;
        if (this.g_PrnStartFlag == 1) {
            byRet = RecvBytes(pbyRecvData, 0, 1, 20000);
        } else
            byRet = RecvBytes(pbyRecvData, 0, 1, dwTimeoutMs);

        if ((1 != byRet) || (2 != pbyRecvData[0])) {
            return -1;
        }
        byRet = RecvBytes(pbyRecvData, 1, 4, 200);
        if (4 != byRet) {
            return ErrorDefine.RECV_PACKET_ERROR;
        }
        wDataLen = (pbyRecvData[3] & 0xFF) * 256 + (pbyRecvData[4] & 0xFF);
        pwPacketetLen[0] = (short) (wDataLen + 7);
        if (wDataLen > 2176) {
            return -2511;
        }
        byRet = RecvBytes(pbyRecvData, 5, wDataLen + 2, 500);
        if (wDataLen + 2 != byRet) {
            return ErrorDefine.RECV_PACKET_ERROR;
        }
        Log.e(TAG, "Rev:" + ByteTool.bytearrayToHexString(pbyRecvData, wDataLen + 7));
        byte[] crcdata = new byte[wDataLen + 4];
        byte[] crcReturnt = new byte[2];
        System.arraycopy(pbyRecvData, wDataLen + 5, crcReturnt, 0, 2);
        System.arraycopy(pbyRecvData, 1, crcdata, 0, wDataLen + 4);
        this.Crc16CCITT(crcdata, wDataLen + 4, abyCrc16);
        if (Arrays.equals(crcReturnt, abyCrc16) == true)
            return 0;

        return 0;
    }

    public void Crc16SendPacket(byte[] send, short length, byte byModules, byte byFunction) {

        byte[] sendBuffer = new byte[length + 7];
        byte[] crcdata = new byte[length + 4];
        byte[] crc = new byte[4];

        sendBuffer[0] = 0x02;
        sendBuffer[1] = byModules;
        sendBuffer[2] = byFunction;
        sendBuffer[3] = (byte) (length / 256);
        sendBuffer[4] = (byte) (length % 256);

        if (length != 0)
            System.arraycopy(send, 0, sendBuffer, 5, length);

        System.arraycopy(sendBuffer, 1, crcdata, 0, length + 4);
        this.Crc16CCITT(crcdata, length + 4, crc);
        //QuickCrc32(crcdata, length + 3, crc);
        System.arraycopy(crc, 0, sendBuffer, length + 5, 2);
        //java.util.zip.CRC32();
        Log.e("send:", ByteTool.bytearrayToHexString(sendBuffer, sendBuffer.length));

        this.writeFlush(sendBuffer, sendBuffer.length);

    }


    public void Quick32Crc(byte[] bData, int length, byte[] crcOut) {
        if (serialPort != null) {
            serialPort.QuickCrc32(bData, length, crcOut);
        }
    }

    public void Crc16CCITT(byte[] bData, int length, byte[] crcOut) {
        if (serialPort != null) {
            serialPort.Crc16CCITT(bData, length, crcOut);
        }
    }

    public boolean PowerOn() {
        Log.e("finan","PowerOn");
        return PowerSwitch(1);
    }

    public boolean PowerOff() {
        Log.e("finan","PowerOff");
        return PowerSwitch(0);
    }

    private boolean PowerSwitch(int flag) {

//        if (flag == 1)
//            rkGpioControlNative.ControlGpio(rkGpioControlNative.RK30_PIN0_PC5, 1);
//        else if (flag == 0)
//            rkGpioControlNative.ControlGpio(rkGpioControlNative.RK30_PIN0_PC5, 0);
//
//        int rs = rkGpioControlNative.ReadGpio(rkGpioControlNative.RK30_PIN0_PC5);
//        if (rs == flag) {
//            return true;
//        }
        return false;
    }



    public void msrLightOn(){

        //  rkGpioControlNative.ControlGpio(rkGpioControlNative.MSR_LIGHT, 1);

    }
    public void msrLightOff(){

        // rkGpioControlNative.ControlGpio(rkGpioControlNative.MSR_LIGHT, 0);

    }
    public void icLightOn(){

        //  rkGpioControlNative.ControlGpio(rkGpioControlNative.IC_LIGHT, 1);

    }
    public void icLightOff(){

        // rkGpioControlNative.ControlGpio(rkGpioControlNative.IC_LIGHT, 0);

    }
}
